//
// Created by jack on 2021/2/5.
//

#include "weilapb_defines.h"

#include <WL.Group.pb.h>
#include <WL.Service.pb.h>
#include <pb_decode.h>

#include "weilapb_datafuns.h"

#include "weilapb_commondec.h"
#include "weilapb_error.h"
#include "weilapb_internal.h"

void* weilapb_decodeSubMsgVersionInfo(pb_istream_t* stream, const pb_field_t* field) {
    WL_Group_GroupVersionInfo wlGroupGroupVersionInfo = WL_Group_GroupVersionInfo_init_zero;
    PBLinkItem*               pPbLinkItem             = PB_NULL;

    if (pb_decode(stream, WL_Group_GroupVersionInfo_fields, &wlGroupGroupVersionInfo)) {
        pPbLinkItem = (PBLinkItem*)PB_ALLOC(sizeof(PBLinkItem) + sizeof(PBGroupSimpleInfo));
        if (pPbLinkItem) {
            PBGroupSimpleInfo* pInfo;
            pPbLinkItem->dataSize = sizeof(PBGroupSimpleInfo);
            pInfo                 = (PBGroupSimpleInfo*)pPbLinkItem->data;

            if (wlGroupGroupVersionInfo.has_groupId) {
                pInfo->groupId = wlGroupGroupVersionInfo.groupId;
            }

            if (wlGroupGroupVersionInfo.has_memberVersion) {
                pInfo->memberVersion = wlGroupGroupVersionInfo.memberVersion;
            }

            if (wlGroupGroupVersionInfo.has_groupVersion) {
                pInfo->groupVersion = wlGroupGroupVersionInfo.groupVersion;
            }
        }
    }

    return pPbLinkItem;
}

PBWeilaMsg* weilapb_decodeGetGroupVersionRsp(const PB_UINT8* pData, PB_UINT32 dataSize) {
    WL_Service_ServiceMessage serviceMessage = WL_Service_ServiceMessage_init_zero;
    pb_istream_t              istream;
    PBWeilaMsg*               pWeilaMsg = PB_ALLOC(sizeof(PBWeilaMsg) + sizeof(PBGetGroupVersionRsp));

    istream = pb_istream_from_buffer(pData, dataSize);

    if (pWeilaMsg) {
        PBFieldData           groupVerInfoField;
        PBGetGroupVersionRsp* pGroupVersionRsp = (PBGetGroupVersionRsp*)pWeilaMsg->pContent;
        pWeilaMsg->contentSize                 = sizeof(PBGetGroupVersionRsp);

        weilapb_initDecDataItem(&groupVerInfoField, PB_DATA_TYPE_LINK_SUBMSG, 0, pGroupVersionRsp);
        weilapb_setDecCallback(
            &groupVerInfoField, &serviceMessage.groupMessage.rspGetGroupVersion.versionInfoList, PB_NULL);
        groupVerInfoField.decSubMsg = weilapb_decodeSubMsgVersionInfo;

        if (weilapb_decodeWeilaMsg(pWeilaMsg, &istream, &serviceMessage)) {
            weilapb_addRecyclePointer(pWeilaMsg, RECYCLE_PTR_LINK, pGroupVersionRsp);
            return pWeilaMsg;
        }

        weilapb_freePBLinkList(pGroupVersionRsp);
        weilapb_error(ERR_DECODE, "decode msg data fail");
        PB_FREE(pWeilaMsg);
        pWeilaMsg = PB_NULL;
    } else {
        weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
    }

    return pWeilaMsg;
}

void* weilapb_decodeSubMsgGroupAttr(pb_istream_t* stream, const pb_field_t* field) {
    WL_Group_GroupAttribute wlGroupGroupAttribute = WL_Group_GroupAttribute_init_zero;
    PBLinkItem*             pPbLinkItem           = PB_NULL;

    pPbLinkItem = (PBLinkItem*)PB_ALLOC(sizeof(PBLinkItem) + sizeof(PBGroupAttr));
    if (pPbLinkItem) {
        PBGroupAttr* pInfo;
        PBFieldData  descField;
        PBFieldData  nameField;
        PBFieldData  numberField;
        PBFieldData  avatarField;

        pPbLinkItem->dataSize = sizeof(PBGroupAttr);

        pInfo = (PBGroupAttr*)pPbLinkItem->data;

        weilapb_initDecDataItem(&descField, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_LONG_STRING_LEN, pInfo->desc);
        weilapb_setDecCallback(&descField, &wlGroupGroupAttribute.desc, PB_NULL);

        weilapb_initDecDataItem(&nameField, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_SHORT_STRING_LEN, pInfo->name);
        weilapb_setDecCallback(&nameField, &wlGroupGroupAttribute.name, PB_NULL);

        weilapb_initDecDataItem(&numberField, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_PHONE_NUM_LEN, pInfo->number);
        weilapb_setDecCallback(&numberField, &wlGroupGroupAttribute.number, PB_NULL);

        weilapb_initDecDataItem(&avatarField, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_URL_STRING_LEN, pInfo->avatar);
        weilapb_setDecCallback(&avatarField, &wlGroupGroupAttribute.avatar, PB_NULL);

        if (pb_decode(stream, WL_Group_GroupAttribute_fields, &wlGroupGroupAttribute)) {
            if (wlGroupGroupAttribute.has_groupId) {
                pInfo->groupId = wlGroupGroupAttribute.groupId;
            }

            if (wlGroupGroupAttribute.has_type) {
                pInfo->groupType = wlGroupGroupAttribute.type;
            }

            if (wlGroupGroupAttribute.has_publicType) {
                pInfo->publicType = wlGroupGroupAttribute.publicType;
            }

            if (wlGroupGroupAttribute.has_shutupStatus) {
                pInfo->speechPermission = wlGroupGroupAttribute.shutupStatus;
            }

            if (wlGroupGroupAttribute.has_memberVersion) {
                pInfo->memberVersion = wlGroupGroupAttribute.memberVersion;
            }

            if (wlGroupGroupAttribute.has_ownerId) {
                pInfo->ownerId = wlGroupGroupAttribute.ownerId;
            }

            if (wlGroupGroupAttribute.has_memberCount) {
                pInfo->memberCount = wlGroupGroupAttribute.memberCount;
            }

            if (wlGroupGroupAttribute.has_created) {
                pInfo->createdTimestamp = wlGroupGroupAttribute.created;
            }
        } else {
            PB_FREE(pPbLinkItem);
            pPbLinkItem = PB_NULL;
        }
    }

    return pPbLinkItem;
}

PBWeilaMsg* weilapb_decodeGetGroupAttrRsp(const PB_UINT8* pData, PB_UINT32 dataSize) {
    WL_Service_ServiceMessage serviceMessage = WL_Service_ServiceMessage_init_zero;
    pb_istream_t              istream;
    PBWeilaMsg*               pWeilaMsg = PB_ALLOC(sizeof(PBWeilaMsg) + sizeof(PBGetGroupAttrRsp));

    istream = pb_istream_from_buffer(pData, dataSize);

    if (pWeilaMsg) {
        PBFieldData        groupAttrField;
        PBGetGroupAttrRsp* pPbGetGroupAttrRsp = (PBGetGroupAttrRsp*)pWeilaMsg->pContent;
        pWeilaMsg->contentSize                = sizeof(PBGetGroupAttrRsp);

        weilapb_initDecDataItem(&groupAttrField, PB_DATA_TYPE_LINK_SUBMSG, 0, pPbGetGroupAttrRsp);
        weilapb_setDecCallback(
            &groupAttrField, &serviceMessage.groupMessage.rspGetGroupAttribute.groupAttrList, PB_NULL);
        groupAttrField.decSubMsg = weilapb_decodeSubMsgGroupAttr;

        if (weilapb_decodeWeilaMsg(pWeilaMsg, &istream, &serviceMessage)) {
            weilapb_addRecyclePointer(pWeilaMsg, RECYCLE_PTR_LINK, pPbGetGroupAttrRsp);
            return pWeilaMsg;
        }

        weilapb_freePBLinkList(pPbGetGroupAttrRsp);
        weilapb_error(ERR_DECODE, "decode msg data fail");
        PB_FREE(pWeilaMsg);
        pWeilaMsg = PB_NULL;
    } else {
        weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
    }

    return pWeilaMsg;
}

void* weilapb_decodeSubMsgMemberInfo(pb_istream_t* stream, const pb_field_t* field) {
    WL_Group_GroupMemberInfo wlGroupGroupMemberInfo = WL_Group_GroupMemberInfo_init_zero;
    PBLinkItem*              pPbLinkItem            = PB_NULL;

    pPbLinkItem = (PBLinkItem*)PB_ALLOC(sizeof(PBLinkItem) + sizeof(PBMemberInfo));
    if (pPbLinkItem) {
        PBMemberInfo* pInfo;
        PBFieldData   remarkField;
        pPbLinkItem->dataSize = sizeof(PBMemberInfo);
        pInfo                 = (PBMemberInfo*)pPbLinkItem->data;

        weilapb_initDecDataItem(&remarkField, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_NORMAL_STRING_LEN, pInfo->remark);
        weilapb_setDecCallback(&remarkField, &wlGroupGroupMemberInfo.remark, PB_NULL);

        if (pb_decode(stream, WL_Group_GroupMemberInfo_fields, &wlGroupGroupMemberInfo)) {
            if (wlGroupGroupMemberInfo.has_userId) {
                pInfo->userId = wlGroupGroupMemberInfo.userId;
            }

            if (wlGroupGroupMemberInfo.has_status) {
                pInfo->status = wlGroupGroupMemberInfo.status;
            }

            if (wlGroupGroupMemberInfo.has_shutupStatus) {
                pInfo->speechPermission = wlGroupGroupMemberInfo.shutupStatus;
            }

            if (wlGroupGroupMemberInfo.has_shutupTimeout) {
                pInfo->silentDuration = wlGroupGroupMemberInfo.shutupTimeout;
            }

            if (wlGroupGroupMemberInfo.has_tts) {
                pInfo->tts = wlGroupGroupMemberInfo.tts;
            }

            if (wlGroupGroupMemberInfo.has_type) {
                pInfo->memberType = wlGroupGroupMemberInfo.type;
            }

            if (wlGroupGroupMemberInfo.has_prority) {
                pInfo->priority = wlGroupGroupMemberInfo.prority;
            }
        } else {
            PB_FREE(pPbLinkItem);
            pPbLinkItem = PB_NULL;
        }
    }

    return pPbLinkItem;
}

PBWeilaMsg* weilapb_decodeCreateGroupRsp(const PB_UINT8* pData, PB_UINT32 dataSize) {
    WL_Service_ServiceMessage serviceMessage = WL_Service_ServiceMessage_init_zero;
    pb_istream_t              istream;
    PBWeilaMsg*               pWeilaMsg = PB_ALLOC(sizeof(PBWeilaMsg) + sizeof(PBCreateGroupRsp));

    istream = pb_istream_from_buffer(pData, dataSize);

    if (pWeilaMsg) {
        PBFieldData memberInfoField;
        PBFieldData descField;
        PBFieldData nameField;
        PBFieldData numberField;
        PBFieldData avatarField;

        PBCreateGroupRsp* pPbCreateGroupRsp = (PBCreateGroupRsp*)pWeilaMsg->pContent;
        pWeilaMsg->contentSize              = sizeof(PBCreateGroupRsp);

        weilapb_initDecDataItem(&memberInfoField, PB_DATA_TYPE_LINK_SUBMSG, 0, &pPbCreateGroupRsp->memberInfoList);
        weilapb_setDecCallback(&memberInfoField, &serviceMessage.groupMessage.rspCreateGroup.memberInfoList, PB_NULL);
        memberInfoField.decSubMsg = weilapb_decodeSubMsgMemberInfo;

        weilapb_initDecDataItem(
            &descField, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_LONG_STRING_LEN, pPbCreateGroupRsp->groupAttr.desc);
        weilapb_setDecCallback(&descField, &serviceMessage.groupMessage.rspCreateGroup.groupAttribute.desc, PB_NULL);

        weilapb_initDecDataItem(
            &nameField, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_SHORT_STRING_LEN, pPbCreateGroupRsp->groupAttr.name);
        weilapb_setDecCallback(&nameField, &serviceMessage.groupMessage.rspCreateGroup.groupAttribute.name, PB_NULL);

        weilapb_initDecDataItem(
            &numberField, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_PHONE_NUM_LEN, pPbCreateGroupRsp->groupAttr.number);
        weilapb_setDecCallback(
            &numberField, &serviceMessage.groupMessage.rspCreateGroup.groupAttribute.number, PB_NULL);

        weilapb_initDecDataItem(
            &avatarField, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_URL_STRING_LEN, pPbCreateGroupRsp->groupAttr.avatar);
        weilapb_setDecCallback(
            &avatarField, &serviceMessage.groupMessage.rspCreateGroup.groupAttribute.avatar, PB_NULL);

        if (weilapb_decodeWeilaMsg(pWeilaMsg, &istream, &serviceMessage)) {
            WL_Group_GroupAttribute* pWlGroupGroupAttribute;
            weilapb_addRecyclePointer(pWeilaMsg, RECYCLE_PTR_LINK, &pPbCreateGroupRsp->memberInfoList);

            pWlGroupGroupAttribute = &serviceMessage.groupMessage.rspCreateGroup.groupAttribute;
            if (pWlGroupGroupAttribute->has_groupId) {
                pPbCreateGroupRsp->groupAttr.groupId = pWlGroupGroupAttribute->groupId;
            }

            if (pWlGroupGroupAttribute->has_type) {
                pPbCreateGroupRsp->groupAttr.groupType = pWlGroupGroupAttribute->type;
            }

            if (pWlGroupGroupAttribute->has_publicType) {
                pPbCreateGroupRsp->groupAttr.publicType = pWlGroupGroupAttribute->publicType;
            }

            if (pWlGroupGroupAttribute->has_shutupStatus) {
                pPbCreateGroupRsp->groupAttr.speechPermission = pWlGroupGroupAttribute->shutupStatus;
            }

            if (pWlGroupGroupAttribute->has_memberVersion) {
                pPbCreateGroupRsp->groupAttr.memberVersion = pWlGroupGroupAttribute->memberVersion;
            }

            if (pWlGroupGroupAttribute->has_ownerId) {
                pPbCreateGroupRsp->groupAttr.ownerId = pWlGroupGroupAttribute->ownerId;
            }

            if (pWlGroupGroupAttribute->has_memberCount) {
                pPbCreateGroupRsp->groupAttr.memberCount = pWlGroupGroupAttribute->memberCount;
            }

            if (pWlGroupGroupAttribute->has_created) {
                pPbCreateGroupRsp->groupAttr.createdTimestamp = pWlGroupGroupAttribute->created;
            }

            return pWeilaMsg;
        }

        weilapb_freePBLinkList(&pPbCreateGroupRsp->memberInfoList);
        weilapb_error(ERR_DECODE, "decode msg data fail");
        PB_FREE(pWeilaMsg);
        pWeilaMsg = PB_NULL;
    } else {
        weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
    }

    return pWeilaMsg;
}

PBWeilaMsg* weilapb_decodeChangeGroupAttrNtf(const PB_UINT8* pData, PB_UINT32 dataSize) {
    WL_Service_ServiceMessage serviceMessage = WL_Service_ServiceMessage_init_zero;
    pb_istream_t              istream;
    PBWeilaMsg*               pWeilaMsg = PB_ALLOC(sizeof(PBWeilaMsg) + sizeof(PBGroupAttr));

    istream = pb_istream_from_buffer(pData, dataSize);

    if (pWeilaMsg) {
        PBGroupAttr*             pInfo;
        WL_Group_GroupAttribute* pAttr;
        PBFieldData              descField;
        PBFieldData              nameField;
        PBFieldData              numberField;
        PBFieldData              avatarField;

        pWeilaMsg->contentSize = sizeof(PBGroupAttr);

        pInfo = (PBGroupAttr*)pWeilaMsg->pContent;
        pAttr = &serviceMessage.groupMessage.ntfChangeGroupAttribute.groupAttribute;

        weilapb_initDecDataItem(&descField, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_LONG_STRING_LEN, pInfo->desc);
        weilapb_setDecCallback(&descField, &pAttr->desc, PB_NULL);

        weilapb_initDecDataItem(&nameField, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_SHORT_STRING_LEN, pInfo->name);
        weilapb_setDecCallback(&nameField, &pAttr->name, PB_NULL);

        weilapb_initDecDataItem(&numberField, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_PHONE_NUM_LEN, pInfo->number);
        weilapb_setDecCallback(&numberField, &pAttr->number, PB_NULL);

        weilapb_initDecDataItem(&avatarField, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_URL_STRING_LEN, pInfo->avatar);
        weilapb_setDecCallback(&avatarField, &pAttr->avatar, PB_NULL);

        if (weilapb_decodeWeilaMsg(pWeilaMsg, &istream, &serviceMessage)) {
            if (pAttr->has_groupId) {
                pInfo->groupId = pAttr->groupId;
            }

            if (pAttr->has_type) {
                pInfo->groupType = pAttr->type;
            }

            if (pAttr->has_publicType) {
                pInfo->publicType = pAttr->publicType;
            }

            if (pAttr->has_shutupStatus) {
                pInfo->speechPermission = pAttr->shutupStatus;
            }

            if (pAttr->has_memberVersion) {
                pInfo->memberVersion = pAttr->memberVersion;
            }

            if (pAttr->has_ownerId) {
                pInfo->ownerId = pAttr->ownerId;
            }

            if (pAttr->has_memberCount) {
                pInfo->memberCount = pAttr->memberCount;
            }

            if (pAttr->has_created) {
                pInfo->createdTimestamp = pAttr->created;
            }

            return pWeilaMsg;
        }

        weilapb_error(ERR_DECODE, "decode msg data fail");
        PB_FREE(pWeilaMsg);
        pWeilaMsg = PB_NULL;
    } else {
        weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
    }

    return pWeilaMsg;
}

PBWeilaMsg* weilapb_decodeGetGroupInfoRsp(const PB_UINT8* pData, PB_UINT32 dataSize) {
    WL_Service_ServiceMessage serviceMessage = WL_Service_ServiceMessage_init_zero;
    pb_istream_t              istream;
    PBWeilaMsg*               pWeilaMsg = PB_ALLOC(sizeof(PBWeilaMsg) + sizeof(PBGroupInfo));

    istream = pb_istream_from_buffer(pData, dataSize);

    if (pWeilaMsg) {
        PBGroupInfo*             pPbGroupInfo = (PBGroupInfo*)pWeilaMsg->pContent;
        PBFieldData              memberInfoField;
        PBFieldData              descField;
        PBFieldData              nameField;
        PBFieldData              numberField;
        PBFieldData              avatarField;
        WL_Group_GroupAttribute* pAttr;

        pWeilaMsg->contentSize = sizeof(PBGroupInfo);
        pAttr                  = &serviceMessage.groupMessage.rspGetGroupInfo.groupAttribute;

        weilapb_initDecDataItem(&memberInfoField, PB_DATA_TYPE_LINK_SUBMSG, 0, &pPbGroupInfo->memberInfoList);
        weilapb_setDecCallback(&memberInfoField, &serviceMessage.groupMessage.rspGetGroupInfo.memberInfoList, PB_NULL);
        memberInfoField.decSubMsg = weilapb_decodeSubMsgMemberInfo;

        weilapb_initDecDataItem(
            &descField, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_LONG_STRING_LEN, pPbGroupInfo->groupAttr.desc);
        weilapb_setDecCallback(&descField, &pAttr->desc, PB_NULL);

        weilapb_initDecDataItem(
            &nameField, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_SHORT_STRING_LEN, pPbGroupInfo->groupAttr.name);
        weilapb_setDecCallback(&nameField, &pAttr->name, PB_NULL);

        weilapb_initDecDataItem(
            &numberField, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_PHONE_NUM_LEN, pPbGroupInfo->groupAttr.number);
        weilapb_setDecCallback(&numberField, &pAttr->number, PB_NULL);

        weilapb_initDecDataItem(
            &avatarField, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_URL_STRING_LEN, pPbGroupInfo->groupAttr.avatar);
        weilapb_setDecCallback(&avatarField, &pAttr->avatar, PB_NULL);

        if (weilapb_decodeWeilaMsg(pWeilaMsg, &istream, &serviceMessage)) {
            weilapb_addRecyclePointer(pWeilaMsg, RECYCLE_PTR_LINK, &pPbGroupInfo->memberInfoList);
            if (serviceMessage.groupMessage.rspGetGroupInfo.has_memberPartial) {
                pPbGroupInfo->partial = serviceMessage.groupMessage.rspGetGroupInfo.memberPartial;
            }

            if (pAttr->has_groupId) {
                pPbGroupInfo->groupAttr.groupId = pAttr->groupId;
            }

            if (pAttr->has_type) {
                pPbGroupInfo->groupAttr.groupType = pAttr->type;
            }

            if (pAttr->has_publicType) {
                pPbGroupInfo->groupAttr.publicType = pAttr->publicType;
            }

            if (pAttr->has_shutupStatus) {
                pPbGroupInfo->groupAttr.speechPermission = pAttr->shutupStatus;
            }

            if (pAttr->has_memberVersion) {
                pPbGroupInfo->groupAttr.memberVersion = pAttr->memberVersion;
            }

            if (pAttr->has_ownerId) {
                pPbGroupInfo->groupAttr.ownerId = pAttr->ownerId;
            }

            if (pAttr->has_memberCount) {
                pPbGroupInfo->groupAttr.memberCount = pAttr->memberCount;
            }

            if (pAttr->has_created) {
                pPbGroupInfo->groupAttr.createdTimestamp = pAttr->created;
            }

            return pWeilaMsg;
        }

        weilapb_freePBLinkList(&pPbGroupInfo->memberInfoList);
        weilapb_error(ERR_DECODE, "decode msg data fail");
        PB_FREE(pWeilaMsg);
        pWeilaMsg = PB_NULL;
    } else {
        weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
    }

    return pWeilaMsg;
}

PBWeilaMsg* weilapb_decodeGetGroupBlackListRsp(const PB_UINT8* pData, PB_UINT32 dataSize) {
    WL_Service_ServiceMessage serviceMessage = WL_Service_ServiceMessage_init_zero;
    pb_istream_t              istream;
    PBWeilaMsg*               pWeilaMsg = PB_ALLOC(sizeof(PBWeilaMsg) + sizeof(PBGetGroupBlackListRsp));

    istream = pb_istream_from_buffer(pData, dataSize);

    if (pWeilaMsg) {
        PBFieldData             userInfoField;
        PBGetGroupBlackListRsp* pPbGetGroupBlackListRsp = (PBGetGroupBlackListRsp*)pWeilaMsg->pContent;
        pWeilaMsg->contentSize                          = sizeof(PBGetGroupBlackListRsp);

        weilapb_initDecDataItem(&userInfoField, PB_DATA_TYPE_LINK_SUBMSG, 0, pPbGetGroupBlackListRsp);
        weilapb_setDecCallback(&userInfoField, &serviceMessage.groupMessage.rspGetGroupBlackList.userInfos, PB_NULL);
        userInfoField.decSubMsg = weilapb_decodeSubMsgUserInfo;

        if (weilapb_decodeWeilaMsg(pWeilaMsg, &istream, &serviceMessage)) {
            weilapb_addRecyclePointer(pWeilaMsg, RECYCLE_PTR_LINK, pPbGetGroupBlackListRsp);
            return pWeilaMsg;
        }

        weilapb_freePBLinkList(pPbGetGroupBlackListRsp);
        weilapb_error(ERR_DECODE, "decode msg data fail");
        PB_FREE(pWeilaMsg);
        pWeilaMsg = PB_NULL;
    } else {
        weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
    }

    return pWeilaMsg;
}

PBWeilaMsg* weilapb_decodeGetGroupOnlineMemberRsp(const PB_UINT8* pData, PB_UINT32 dataSize) {
    WL_Service_ServiceMessage serviceMessage = WL_Service_ServiceMessage_init_zero;
    pb_istream_t              istream;
    PBWeilaMsg*               pWeilaMsg = PB_NULL;
    PB_UINT32*                pArray;
    istream = pb_istream_from_buffer(pData, dataSize);

    pArray = (PB_UINT32*)PB_ALLOC(20 * sizeof(PB_UINT32));

    if (pArray) {
        PBFieldData userIdField;
        PBWeilaMsg  weilaMsg;
        weilapb_initDecDataItem(&userIdField, PB_DATA_TYPE_ARRAY_UINT32, 20, pArray);
        weilapb_setDecCallback(&userIdField, &serviceMessage.groupMessage.rspGetGroupOnlineMember.userIdList, PB_NULL);

        memset(&weilaMsg, 0, sizeof(PBWeilaMsg));
        if (weilapb_decodeWeilaMsg(&weilaMsg, &istream, &serviceMessage)) {
            if (serviceMessage.serviceHead.resultCode == 0) {
                pWeilaMsg = (PBWeilaMsg*)PB_ALLOC(sizeof(PBWeilaMsg) + sizeof(PBArray)
                                                  + sizeof(PB_UINT32) * userIdField.dataSize);
                if (pWeilaMsg) {
                    PBArray* pPbArray = (PBArray*)(pWeilaMsg->pContent);
                    memcpy(pWeilaMsg, &weilaMsg, sizeof(PBWeilaMsg));
                    pWeilaMsg->contentSize = sizeof(PBArray) + sizeof(PB_UINT32) * userIdField.dataSize;
                    pPbArray->arrayType    = PB_DATA_TYPE_ARRAY_UINT32;
                    pPbArray->listCount    = userIdField.dataSize;
                    memcpy(pPbArray->data, userIdField.pData, sizeof(PB_UINT32) * userIdField.dataSize);
                } else {
                    weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
                }
            } else {
                pWeilaMsg = (PBWeilaMsg*)PB_ALLOC(sizeof(PBWeilaMsg));
                if (pWeilaMsg) {
                    memcpy(pWeilaMsg, &weilaMsg, sizeof(PBWeilaMsg));
                } else {
                    weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
                }
            }

            PB_FREE(pArray);

            return pWeilaMsg;
        }

        weilapb_error(ERR_DECODE, "decode msg data fail");
        PB_FREE(pArray);
    } else {
        weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
    }

    return pWeilaMsg;
}

PBWeilaMsg* weilapb_decodeDelGroupNtf(const PB_UINT8* pData, PB_UINT32 dataSize) {
    WL_Service_ServiceMessage serviceMessage = WL_Service_ServiceMessage_init_zero;
    pb_istream_t              istream;
    PBWeilaMsg*               pWeilaMsg = PB_ALLOC(sizeof(PBWeilaMsg) + sizeof(PB_UINT64));

    istream = pb_istream_from_buffer(pData, dataSize);

    if (pWeilaMsg) {
        PB_UINT64* pGroupId    = (PB_UINT64*)pWeilaMsg->pContent;
        pWeilaMsg->contentSize = sizeof(PB_UINT64);
        if (weilapb_decodeWeilaMsg(pWeilaMsg, &istream, &serviceMessage)) {
            if (serviceMessage.groupMessage.ntfDeleteGroup.has_groupId) {
                *pGroupId = serviceMessage.groupMessage.ntfDeleteGroup.groupId;
            }

            return pWeilaMsg;
        }

        weilapb_error(ERR_DECODE, "decode msg data fail");
        PB_FREE(pWeilaMsg);
        pWeilaMsg = PB_NULL;
    } else {
        weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
    }

    return pWeilaMsg;
}

PBWeilaMsg* weilapb_decodeDelMemberNtf(const PB_UINT8* pData, PB_UINT32 dataSize) {
    WL_Service_ServiceMessage serviceMessage = WL_Service_ServiceMessage_init_zero;
    pb_istream_t              istream;
    PBWeilaMsg*               pWeilaMsg = PB_NULL;
    PB_UINT32*                pArray;
    istream = pb_istream_from_buffer(pData, dataSize);
    pArray  = (PB_UINT32*)PB_ALLOC(sizeof(PB_UINT32) * 20);

    if (pArray) {
        PBFieldData userIdField;
        PBWeilaMsg  weilaMsg;
        weilapb_initDecDataItem(&userIdField, PB_DATA_TYPE_ARRAY_UINT32, 20, pArray);
        weilapb_setDecCallback(&userIdField, &serviceMessage.groupMessage.ntfDeleteMember.userIdList, PB_NULL);

        memset(&weilaMsg, 0, sizeof(PBWeilaMsg));
        if (weilapb_decodeWeilaMsg(&weilaMsg, &istream, &serviceMessage)) {
            if (serviceMessage.serviceHead.resultCode == 0) {
                pWeilaMsg = (PBWeilaMsg*)PB_ALLOC(sizeof(PBWeilaMsg) + sizeof(PBDelMemberNtf)
                                                  + sizeof(PB_UINT32) * userIdField.dataSize);
                if (pWeilaMsg) {
                    PBDelMemberNtf* pPbDelMemberNtf = (PBDelMemberNtf*)pWeilaMsg->pContent;
                    memcpy(pWeilaMsg, &weilaMsg, sizeof(PBWeilaMsg));
                    pWeilaMsg->contentSize = sizeof(PBDelMemberNtf) + sizeof(PB_UINT32) * userIdField.dataSize;
                    memcpy(pPbDelMemberNtf->userList.data, userIdField.pData, userIdField.dataSize * sizeof(PB_UINT32));
                    pPbDelMemberNtf->userList.listCount = userIdField.dataSize;
                    pPbDelMemberNtf->userList.arrayType = PB_DATA_TYPE_ARRAY_UINT32;

                    if (serviceMessage.groupMessage.ntfDeleteMember.has_groupId) {
                        pPbDelMemberNtf->groupId = serviceMessage.groupMessage.ntfDeleteMember.groupId;
                    }

                    if (serviceMessage.groupMessage.ntfDeleteMember.has_initiatorId) {
                        pPbDelMemberNtf->operatorId = serviceMessage.groupMessage.ntfDeleteMember.initiatorId;
                    }

                    PB_FREE(pArray);
                    return pWeilaMsg;
                } else {
                    weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
                }
            } else {
                pWeilaMsg = (PBWeilaMsg*)PB_ALLOC(sizeof(PBWeilaMsg));
                if (pWeilaMsg) {
                    memcpy(pWeilaMsg, &weilaMsg, sizeof(PBWeilaMsg));
                } else {
                    weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
                }
            }
        } else {
            weilapb_error(ERR_DECODE, "decode msg data fail");
        }
    } else {
        weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
    }
    PB_FREE(pArray);

    return pWeilaMsg;
}

PBWeilaMsg* weilapb_decodeGetMemberUserInfoRsp(const PB_UINT8* pData, PB_UINT32 dataSize) {
    WL_Service_ServiceMessage serviceMessage = WL_Service_ServiceMessage_init_zero;
    pb_istream_t              istream;
    PBWeilaMsg*               pWeilaMsg = PB_ALLOC(sizeof(PBWeilaMsg) + sizeof(PBGetMemberUserInfoRsp));

    istream = pb_istream_from_buffer(pData, dataSize);

    if (pWeilaMsg) {
        PBFieldData             userInfoField;
        PBGetMemberUserInfoRsp* pPbGetMemberUserInfoRsp;
        pWeilaMsg->contentSize = sizeof(PBGetMemberUserInfoRsp);

        pPbGetMemberUserInfoRsp = (PBGetMemberUserInfoRsp*)pWeilaMsg->pContent;

        weilapb_initDecDataItem(&userInfoField, PB_DATA_TYPE_LINK_SUBMSG, 0, pPbGetMemberUserInfoRsp);
        weilapb_setDecCallback(&userInfoField, &serviceMessage.groupMessage.rspGetMemberUserInfo.userInfoList, PB_NULL);
        userInfoField.decSubMsg = weilapb_decodeSubMsgUserInfo;

        if (weilapb_decodeWeilaMsg(pWeilaMsg, &istream, &serviceMessage)) {
            weilapb_addRecyclePointer(pWeilaMsg, RECYCLE_PTR_LINK, pPbGetMemberUserInfoRsp);
            return pWeilaMsg;
        }

        weilapb_freePBLinkList(pPbGetMemberUserInfoRsp);
        weilapb_error(ERR_DECODE, "decode msg data fail");
        PB_FREE(pWeilaMsg);
        pWeilaMsg = PB_NULL;
    } else {
        weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
    }

    return pWeilaMsg;
}

PBWeilaMsg* weilapb_decodeChangeMemberInfoNtf(const PB_UINT8* pData, PB_UINT32 dataSize) {
    WL_Service_ServiceMessage serviceMessage = WL_Service_ServiceMessage_init_zero;
    pb_istream_t              istream;
    PBWeilaMsg*               pWeilaMsg = PB_ALLOC(sizeof(PBWeilaMsg) + sizeof(PBMemberChangeNtf));

    istream = pb_istream_from_buffer(pData, dataSize);

    if (pWeilaMsg) {
        PBMemberChangeNtf* pPbMemberChangeNtf;
        PBFieldData        remarkField;
        pWeilaMsg->contentSize = sizeof(PBMemberChangeNtf);
        pPbMemberChangeNtf     = (PBMemberChangeNtf*)pWeilaMsg->pContent;

        weilapb_initDecDataItem(
            &remarkField, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_NORMAL_STRING_LEN, pPbMemberChangeNtf->memberInfo.remark);
        weilapb_setDecCallback(
            &remarkField, &serviceMessage.groupMessage.ntfChangeMemberInfo.memberInfo.remark, PB_NULL);

        if (weilapb_decodeWeilaMsg(pWeilaMsg, &istream, &serviceMessage)) {
            if (serviceMessage.groupMessage.ntfChangeMemberInfo.has_groupId) {
                pPbMemberChangeNtf->groupId = serviceMessage.groupMessage.ntfChangeMemberInfo.groupId;
            }

            if (serviceMessage.groupMessage.ntfChangeMemberInfo.memberInfo.has_userId) {
                pPbMemberChangeNtf->memberInfo.userId =
                    serviceMessage.groupMessage.ntfChangeMemberInfo.memberInfo.userId;
            }

            if (serviceMessage.groupMessage.ntfChangeMemberInfo.memberInfo.has_status) {
                pPbMemberChangeNtf->memberInfo.status =
                    serviceMessage.groupMessage.ntfChangeMemberInfo.memberInfo.status;
            }

            if (serviceMessage.groupMessage.ntfChangeMemberInfo.memberInfo.has_shutupStatus) {
                pPbMemberChangeNtf->memberInfo.speechPermission =
                    serviceMessage.groupMessage.ntfChangeMemberInfo.memberInfo.shutupStatus;
            }

            if (serviceMessage.groupMessage.ntfChangeMemberInfo.memberInfo.has_shutupTimeout) {
                pPbMemberChangeNtf->memberInfo.silentDuration =
                    serviceMessage.groupMessage.ntfChangeMemberInfo.memberInfo.shutupTimeout;
            }

            if (serviceMessage.groupMessage.ntfChangeMemberInfo.memberInfo.has_tts) {
                pPbMemberChangeNtf->memberInfo.tts = serviceMessage.groupMessage.ntfChangeMemberInfo.memberInfo.tts;
            }

            if (serviceMessage.groupMessage.ntfChangeMemberInfo.memberInfo.has_type) {
                pPbMemberChangeNtf->memberInfo.memberType =
                    serviceMessage.groupMessage.ntfChangeMemberInfo.memberInfo.type;
            }

            if (serviceMessage.groupMessage.ntfChangeMemberInfo.memberInfo.has_prority) {
                pPbMemberChangeNtf->memberInfo.priority =
                    serviceMessage.groupMessage.ntfChangeMemberInfo.memberInfo.prority;
            }

            return pWeilaMsg;
        }

        weilapb_error(ERR_DECODE, "decode msg data fail");
        PB_FREE(pWeilaMsg);
        pWeilaMsg = PB_NULL;
    } else {
        weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
    }

    return pWeilaMsg;
}

PBWeilaMsg* weilapb_decodeAnswerGroupInviteNtf(const PB_UINT8* pData, PB_UINT32 dataSize) {
    WL_Service_ServiceMessage serviceMessage = WL_Service_ServiceMessage_init_zero;
    pb_istream_t              istream;
    PBWeilaMsg*               pWeilaMsg = PB_ALLOC(sizeof(PBWeilaMsg) + sizeof(PBAnswerGroupInviteNtf));

    istream = pb_istream_from_buffer(pData, dataSize);

    if (pWeilaMsg) {
        PBAnswerGroupInviteNtf* pPbAnswerGroupInviteNtf;
        pWeilaMsg->contentSize  = sizeof(PBAnswerGroupInviteNtf);
        pPbAnswerGroupInviteNtf = (PBAnswerGroupInviteNtf*)pWeilaMsg->pContent;

        if (weilapb_decodeWeilaMsg(pWeilaMsg, &istream, &serviceMessage)) {
            if (serviceMessage.groupMessage.ntfAnswerGroupInvite.has_groupId) {
                pPbAnswerGroupInviteNtf->groupId = serviceMessage.groupMessage.ntfAnswerGroupInvite.groupId;
            }

            if (serviceMessage.groupMessage.ntfAnswerGroupInvite.has_inviterId) {
                pPbAnswerGroupInviteNtf->inviterId = serviceMessage.groupMessage.ntfAnswerGroupInvite.inviterId;
            }

            if (serviceMessage.groupMessage.ntfAnswerGroupInvite.has_inviteeId) {
                pPbAnswerGroupInviteNtf->inviteeId = serviceMessage.groupMessage.ntfAnswerGroupInvite.inviteeId;
            }

            if (serviceMessage.groupMessage.ntfAnswerGroupInvite.has_status) {
                pPbAnswerGroupInviteNtf->status = serviceMessage.groupMessage.ntfAnswerGroupInvite.status;
            }

            if (serviceMessage.groupMessage.ntfAnswerGroupInvite.has_updated) {
                pPbAnswerGroupInviteNtf->createdTimestamp = serviceMessage.groupMessage.ntfAnswerGroupInvite.updated;
            }

            return pWeilaMsg;
        }

        weilapb_error(ERR_DECODE, "decode msg data fail");
        PB_FREE(pWeilaMsg);
        pWeilaMsg = PB_NULL;
    } else {
        weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
    }

    return pWeilaMsg;
}

PBWeilaMsg* weilapb_decodeGroupJoinNtf(const PB_UINT8* pData, PB_UINT32 dataSize) {
    WL_Service_ServiceMessage serviceMessage = WL_Service_ServiceMessage_init_zero;
    pb_istream_t              istream;
    PBWeilaMsg*               pWeilaMsg = PB_ALLOC(sizeof(PBWeilaMsg) + sizeof(PBGroupJoinNtf));

    istream = pb_istream_from_buffer(pData, dataSize);

    if (pWeilaMsg) {
        PBGroupJoinNtf*     pPbGroupJoinNtf;
        PBFieldData         detailField;
        WL_Common_UserInfo* pAttr;
        PBFieldData         fieldData[USER_COUNT];
        pWeilaMsg->contentSize = sizeof(PBGroupJoinNtf);

        pPbGroupJoinNtf = (PBGroupJoinNtf*)pWeilaMsg->pContent;
        pAttr           = &(serviceMessage.groupMessage.ntfGroupJoin.userInfo);
        weilapb_prepareUserInfoField(fieldData, pAttr, &pPbGroupJoinNtf->userInfo);

        weilapb_initDecDataItem(
            &detailField, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_NORMAL_STRING_LEN, pPbGroupJoinNtf->detail);
        weilapb_setDecCallback(&detailField, &serviceMessage.groupMessage.ntfGroupJoin.detail, PB_NULL);

        if (weilapb_decodeWeilaMsg(pWeilaMsg, &istream, &serviceMessage)) {
            if (serviceMessage.groupMessage.ntfGroupJoin.has_groupId) {
                pPbGroupJoinNtf->groupId = serviceMessage.groupMessage.ntfGroupJoin.groupId;
            }

            if (serviceMessage.groupMessage.ntfGroupJoin.has_joinId) {
                pPbGroupJoinNtf->joinId = serviceMessage.groupMessage.ntfGroupJoin.joinId;
            }

            return pWeilaMsg;
        }

        weilapb_error(ERR_DECODE, "decode msg data fail");
        PB_FREE(pWeilaMsg);
        pWeilaMsg = PB_NULL;
    } else {
        weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
    }

    return pWeilaMsg;
}

PBWeilaMsg* weilapb_decodeAnswerGroupJoinNtf(const PB_UINT8* pData, PB_UINT32 dataSize) {
    WL_Service_ServiceMessage serviceMessage = WL_Service_ServiceMessage_init_zero;
    pb_istream_t              istream;
    PBWeilaMsg*               pWeilaMsg = PB_ALLOC(sizeof(PBWeilaMsg) + sizeof(PBAnswerGroupJoinNtf));

    istream = pb_istream_from_buffer(pData, dataSize);

    if (pWeilaMsg) {
        PBAnswerGroupJoinNtf* pPbAnswerGroupJoinNtf;
        pWeilaMsg->contentSize = sizeof(PBAnswerGroupJoinNtf);
        pPbAnswerGroupJoinNtf  = (PBAnswerGroupJoinNtf*)pWeilaMsg->pContent;

        if (weilapb_decodeWeilaMsg(pWeilaMsg, &istream, &serviceMessage)) {
            if (serviceMessage.groupMessage.ntfAnswerGroupJoin.has_groupId) {
                pPbAnswerGroupJoinNtf->groupId = serviceMessage.groupMessage.ntfAnswerGroupJoin.groupId;
            }

            if (serviceMessage.groupMessage.ntfAnswerGroupJoin.has_joinId) {
                pPbAnswerGroupJoinNtf->joinId = serviceMessage.groupMessage.ntfAnswerGroupJoin.joinId;
            }

            if (serviceMessage.groupMessage.ntfAnswerGroupJoin.has_updated) {
                pPbAnswerGroupJoinNtf->createdTimestamp = serviceMessage.groupMessage.ntfAnswerGroupJoin.updated;
            }

            if (serviceMessage.groupMessage.ntfAnswerGroupJoin.has_status) {
                pPbAnswerGroupJoinNtf->status = serviceMessage.groupMessage.ntfAnswerGroupJoin.status;
            }

            if (serviceMessage.groupMessage.ntfAnswerGroupJoin.has_answerId) {
                pPbAnswerGroupJoinNtf->answerId = serviceMessage.groupMessage.ntfAnswerGroupJoin.answerId;
            }
            return pWeilaMsg;
        }

        weilapb_error(ERR_DECODE, "decode msg data fail");
        PB_FREE(pWeilaMsg);
        pWeilaMsg = PB_NULL;
    } else {
        weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
    }

    return pWeilaMsg;
}

void* weilapb_decodeSubMsgBroadcastInfo(pb_istream_t* stream, const pb_field_t* field) {
    WL_Group_GroupBroadcastInfo wlGroupGroupBroadcastInfo = WL_Group_GroupBroadcastInfo_init_zero;
    PBLinkItem*                 pbLinkItem                = PB_ALLOC(sizeof(PBLinkItem) + sizeof(PBBroadcastInfo));

    if (pbLinkItem) {
        PBBroadcastInfo* pInfo;
        pbLinkItem->dataSize = sizeof(PBBroadcastInfo);

        pInfo = (PBBroadcastInfo*)pbLinkItem->data;
        if (pb_decode(stream, WL_Group_GroupBroadcastInfo_fields, &wlGroupGroupBroadcastInfo)) {
            if (wlGroupGroupBroadcastInfo.has_status) {
                pInfo->status = wlGroupGroupBroadcastInfo.status;
            }

            if (wlGroupGroupBroadcastInfo.has_groupId) {
                pInfo->groupId = wlGroupGroupBroadcastInfo.groupId;
            }

            if (wlGroupGroupBroadcastInfo.has_broadcastId) {
                pInfo->broadcastId = wlGroupGroupBroadcastInfo.broadcastId;
            }
        } else {
            PB_FREE(pbLinkItem);
            pbLinkItem = PB_NULL;
        }
    }

    return pbLinkItem;
}

PBWeilaMsg* weilapb_decodeBroadcastNtf(const PB_UINT8* pData, PB_UINT32 dataSize) {
    WL_Service_ServiceMessage serviceMessage = WL_Service_ServiceMessage_init_zero;
    pb_istream_t              istream;
    PBWeilaMsg*               pWeilaMsg = PB_ALLOC(sizeof(PBWeilaMsg) + sizeof(PBBroadcastNtf));

    istream = pb_istream_from_buffer(pData, dataSize);

    if (pWeilaMsg) {
        PBBroadcastNtf* pPbBroadcastNtf;
        PBFieldData     broadcastInfoField;

        pWeilaMsg->contentSize = sizeof(PBBroadcastNtf);

        pPbBroadcastNtf = (PBBroadcastNtf*)pWeilaMsg->pContent;

        weilapb_initDecDataItem(&broadcastInfoField, PB_DATA_TYPE_LINK_SUBMSG, 0, pPbBroadcastNtf);
        weilapb_setDecCallback(
            &broadcastInfoField, &serviceMessage.groupMessage.ntfGroupBroadcast.broadcastInfoList, PB_NULL);
        broadcastInfoField.decSubMsg = weilapb_decodeSubMsgBroadcastInfo;

        if (weilapb_decodeWeilaMsg(pWeilaMsg, &istream, &serviceMessage)) {
            weilapb_addRecyclePointer(pWeilaMsg, RECYCLE_PTR_LINK, pPbBroadcastNtf);
            return pWeilaMsg;
        }

        weilapb_freePBLinkList(pPbBroadcastNtf);
        weilapb_error(ERR_DECODE, "decode msg data fail");
        PB_FREE(pWeilaMsg);
        pWeilaMsg = PB_NULL;
    } else {
        weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
    }

    return pWeilaMsg;
}

PBWeilaMsg* weilapb_decodeEmbeddedGetGroupVersionRsp(const PB_UINT8* pData, PB_UINT32 dataSize) {
    WL_Service_ServiceMessage serviceMessage = WL_Service_ServiceMessage_init_zero;
    pb_istream_t              istream;
    PBWeilaMsg*               pWeilaMsg = PB_ALLOC(sizeof(PBWeilaMsg) + sizeof(PBGetGroupVersionRsp));

    istream = pb_istream_from_buffer(pData, dataSize);

    if (pWeilaMsg) {
        PBFieldData           groupVerInfoField;
        PBGetGroupVersionRsp* pGroupVersionRsp = (PBGetGroupVersionRsp*)pWeilaMsg->pContent;
        pWeilaMsg->contentSize                 = sizeof(PBGetGroupVersionRsp);

        weilapb_initDecDataItem(&groupVerInfoField, PB_DATA_TYPE_LINK_SUBMSG, 0, pGroupVersionRsp);
        weilapb_setDecCallback(
            &groupVerInfoField, &serviceMessage.groupMessage.rspEmbeddedGetGroupVersion.versionInfoList, PB_NULL);
        groupVerInfoField.decSubMsg = weilapb_decodeSubMsgVersionInfo;

        if (weilapb_decodeWeilaMsg(pWeilaMsg, &istream, &serviceMessage)) {
            weilapb_addRecyclePointer(pWeilaMsg, RECYCLE_PTR_LINK, pGroupVersionRsp);
            return pWeilaMsg;
        }

        weilapb_freePBLinkList(pGroupVersionRsp);
        weilapb_error(ERR_DECODE, "decode msg data fail");
        PB_FREE(pWeilaMsg);
        pWeilaMsg = PB_NULL;
    } else {
        weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
    }

    return pWeilaMsg;
}

void* weilapb_decodeSubMsgEmbeddedGroupInfo(pb_istream_t* stream, const pb_field_t* field) {
    WL_Group_EmbeddedGroupInfo wlGroupEmbeddedGroupInfo = WL_Group_EmbeddedGroupInfo_init_zero;
    PBLinkItem*                pbLinkItem               = PB_ALLOC(sizeof(PBLinkItem) + sizeof(PBEmbeddedGroupInfo));

    if (pbLinkItem) {
        PBEmbeddedGroupInfo* pInfo;
        PBFieldData          name;
        PBFieldData          groupNum;

        pbLinkItem->dataSize = sizeof(PBEmbeddedGroupInfo);
        pInfo                = (PBEmbeddedGroupInfo*)pbLinkItem->data;

        weilapb_initDecDataItem(&name, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_SHORT_STRING_LEN, pInfo->name);
        weilapb_setDecCallback(&name, &wlGroupEmbeddedGroupInfo.name, PB_NULL);

        weilapb_initDecDataItem(&groupNum, PB_DATA_TYPE_FIXED_SIZE_STRING, MAX_PHONE_NUM_LEN, pInfo->number);
        weilapb_setDecCallback(&groupNum, &wlGroupEmbeddedGroupInfo.number, PB_NULL);

        if (pb_decode(stream, WL_Group_EmbeddedGroupInfo_fields, &wlGroupEmbeddedGroupInfo)) {
            if (wlGroupEmbeddedGroupInfo.has_groupId) {
                pInfo->groupId = wlGroupEmbeddedGroupInfo.groupId;
            }

            if (wlGroupEmbeddedGroupInfo.has_type) {
                pInfo->type = wlGroupEmbeddedGroupInfo.type;
            }

            if (wlGroupEmbeddedGroupInfo.has_shieldStatus) {
                pInfo->recvStatus = wlGroupEmbeddedGroupInfo.shieldStatus;
            }

            if (wlGroupEmbeddedGroupInfo.has_locationShare) {
                pInfo->sharedLocation = wlGroupEmbeddedGroupInfo.locationShare;
            }

            if (wlGroupEmbeddedGroupInfo.has_tts) {
                pInfo->tts = wlGroupEmbeddedGroupInfo.tts;
            }

            if (wlGroupEmbeddedGroupInfo.has_shutupStatus) {
                pInfo->speechPermission = wlGroupEmbeddedGroupInfo.shutupStatus;
            }

            if (wlGroupEmbeddedGroupInfo.has_memberCount) {
                pInfo->memberCount = wlGroupEmbeddedGroupInfo.memberCount;
            }

            if (wlGroupEmbeddedGroupInfo.has_ownerId) {
                pInfo->ownerId = wlGroupEmbeddedGroupInfo.ownerId;
            }

            if (wlGroupEmbeddedGroupInfo.has_memberType) {
                pInfo->memberType = wlGroupEmbeddedGroupInfo.memberType;
            }

            if (wlGroupEmbeddedGroupInfo.has_burstType) {
                pInfo->burstType = wlGroupEmbeddedGroupInfo.burstType;
            }

            if (wlGroupEmbeddedGroupInfo.has_version) {
                pInfo->version = wlGroupEmbeddedGroupInfo.version;
            }

            if (wlGroupEmbeddedGroupInfo.has_memberVersion) {
                pInfo->memberVersion = wlGroupEmbeddedGroupInfo.memberVersion;
            }

            if (wlGroupEmbeddedGroupInfo.has_memberPrority) {
                pInfo->priority = wlGroupEmbeddedGroupInfo.memberPrority;
            }

            if (wlGroupEmbeddedGroupInfo.has_memberShutupStatus) {
                pInfo->selfSpeechPermission = wlGroupEmbeddedGroupInfo.memberShutupStatus;
            }

            if (wlGroupEmbeddedGroupInfo.has_memberShutupTimeout) {
                pInfo->shutupTimeout = wlGroupEmbeddedGroupInfo.memberShutupTimeout;
            }
        } else {
            PB_FREE(pbLinkItem);
            pbLinkItem = PB_NULL;
        }
    }

    return pbLinkItem;
}

PBWeilaMsg* weilapb_decodeGetEmbeddedGroupInfoRsp(const PB_UINT8* pData, PB_UINT32 dataSize) {
    WL_Service_ServiceMessage serviceMessage = WL_Service_ServiceMessage_init_zero;
    pb_istream_t              istream;
    PBWeilaMsg*               pWeilaMsg = PB_ALLOC(sizeof(PBWeilaMsg) + sizeof(PBGetEmbeddedGroupInfoRsp));

    istream = pb_istream_from_buffer(pData, dataSize);

    if (pWeilaMsg) {
        PBGetEmbeddedGroupInfoRsp* pbGetEmbeddedGroupInfoRsp;
        PBFieldData                embeddedGroupInfoList;

        pWeilaMsg->contentSize    = sizeof(PBGetEmbeddedGroupInfoRsp);
        pbGetEmbeddedGroupInfoRsp = (PBGetEmbeddedGroupInfoRsp*)pWeilaMsg->pContent;
        weilapb_initDecDataItem(&embeddedGroupInfoList, PB_DATA_TYPE_LINK_SUBMSG, 0, pbGetEmbeddedGroupInfoRsp);
        weilapb_setDecCallback(
            &embeddedGroupInfoList, &serviceMessage.groupMessage.rspEmbeddedGetGroupInfo.groupInfos, PB_NULL);
        embeddedGroupInfoList.decSubMsg = weilapb_decodeSubMsgEmbeddedGroupInfo;

        if (weilapb_decodeWeilaMsg(pWeilaMsg, &istream, &serviceMessage)) {
            weilapb_addRecyclePointer(pWeilaMsg, RECYCLE_PTR_LINK, pbGetEmbeddedGroupInfoRsp);
            return pWeilaMsg;
        }

        weilapb_freePBLinkList(pbGetEmbeddedGroupInfoRsp);
        weilapb_error(ERR_DECODE, "decode msg data fail");
        PB_FREE(pWeilaMsg);
        pWeilaMsg = PB_NULL;
    } else {
        weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
    }

    return pWeilaMsg;
}

PBWeilaMsg* weilapb_decodeNewMemberNtf(const PB_UINT8* pData, PB_UINT32 dataSize) {
    WL_Service_ServiceMessage serviceMessage = WL_Service_ServiceMessage_init_zero;
    pb_istream_t              istream;
    PBWeilaMsg*               pWeilaMsg = PB_ALLOC(sizeof(PBWeilaMsg) + sizeof(PBNewMemberNtf));

    istream = pb_istream_from_buffer(pData, dataSize);
    if (pWeilaMsg) {
        PBNewMemberNtf* pPbNewMemberNtf;
        pWeilaMsg->contentSize = sizeof(PBNewMemberNtf);
        pPbNewMemberNtf        = (PBNewMemberNtf*)pWeilaMsg->pContent;

        if (weilapb_decodeWeilaMsg(pWeilaMsg, &istream, &serviceMessage)) {
            if (serviceMessage.groupMessage.ntfNewMember.has_groupId) {
                pPbNewMemberNtf->groupId = serviceMessage.groupMessage.ntfNewMember.groupId;
            }

            if (serviceMessage.groupMessage.ntfNewMember.has_inviterId) {
                pPbNewMemberNtf->inviterId = serviceMessage.groupMessage.ntfNewMember.inviterId;
            }

            return pWeilaMsg;
        }

        weilapb_error(ERR_DECODE, "decode msg data fail");
        PB_FREE(pWeilaMsg);
        pWeilaMsg = PB_NULL;
    } else {
        weilapb_error(ERR_OUT_OF_MEMORY, "allocate weila msg failed");
    }

    return pWeilaMsg;
}

PBWeilaMsg*
    weilapb_decodeGroupMsg(PB_INT32 commandId, PB_INT32 commandType, const PB_UINT8* pData, PB_UINT32 dataSize) {
    PBWeilaMsg* pWeilaMsg = PB_NULL;

    switch (commandId) {
        case WL_Group_GroupCommandId_GROUP_COMMAND_GET_GROUPVERSION: {
            pWeilaMsg = weilapb_decodeGetGroupVersionRsp(pData, dataSize);
            if (pWeilaMsg) {
                pWeilaMsg->message = WL_GROUP_GET_GROUP_VER_MSG;
            }
        } break;

        case WL_Group_GroupCommandId_GROUP_COMMAND_GET_GROUPATTRIBUTE: {
            pWeilaMsg = weilapb_decodeGetGroupAttrRsp(pData, dataSize);
            if (pWeilaMsg) {
                pWeilaMsg->message = WL_GROUP_GET_GROUP_ATTR_MSG;
            }
        } break;

        case WL_Group_GroupCommandId_GROUP_COMMAND_CREATE_GROUP: {
            pWeilaMsg = weilapb_decodeCreateGroupRsp(pData, dataSize);
            if (pWeilaMsg) {
                pWeilaMsg->message = WL_GROUP_CREATE_GROUP_MSG;
            }
        } break;

        case WL_Group_GroupCommandId_GROUP_COMMAND_DELETE_GROUP: {
            if (commandType == WL_Service_CommandType_COMMAND_RESPONSE) {
                pWeilaMsg = weilapb_decodeEmptyRsp(pData, dataSize);
            } else {
                pWeilaMsg = weilapb_decodeDelGroupNtf(pData, dataSize);
            }
            if (pWeilaMsg) {
                pWeilaMsg->message = WL_GROUP_DEL_GROUP_MSG;
            }
        } break;

        case WL_Group_GroupCommandId_GROUP_COMMAND_DELETE_MEMBER: {
            if (commandType == WL_Service_CommandType_COMMAND_RESPONSE) {
                pWeilaMsg = weilapb_decodeEmptyRsp(pData, dataSize);
            } else {
                pWeilaMsg = weilapb_decodeDelMemberNtf(pData, dataSize);
            }
            if (pWeilaMsg) {
                pWeilaMsg->message = WL_GROUP_DEL_MEMBER_MSG;
            }
        } break;

        case WL_Group_GroupCommandId_GROUP_COMMAND_GET_MEMBER_USERINFO: {
            pWeilaMsg = weilapb_decodeGetMemberUserInfoRsp(pData, dataSize);
            if (pWeilaMsg) {
                pWeilaMsg->message = WL_GROUP_GET_MEMBER_USER_INFO_MSG;
            }
        } break;

        case WL_Group_GroupCommandId_GROUP_COMMAND_GET_ONLINE_MEMBER: {
            pWeilaMsg = weilapb_decodeGetGroupOnlineMemberRsp(pData, dataSize);
            if (pWeilaMsg) {
                pWeilaMsg->message = WL_GROUP_GET_ONLINE_MEMBER_MSG;
            }
        } break;

        case WL_Group_GroupCommandId_GROUP_COMMAND_CHANGE_GROUPATTRIBUTE: {
            if (commandType == WL_Service_CommandType_COMMAND_RESPONSE) {
                pWeilaMsg = weilapb_decodeEmptyRsp(pData, dataSize);
            } else {
                pWeilaMsg = weilapb_decodeChangeGroupAttrNtf(pData, dataSize);
            }
            if (pWeilaMsg) {
                pWeilaMsg->message = WL_GROUP_CHANGE_GROUP_ATTR_MSG;
            }
        } break;

        case WL_Group_GroupCommandId_GROUP_COMMAND_GET_GROUPINFO: {
            pWeilaMsg = weilapb_decodeGetGroupInfoRsp(pData, dataSize);
            if (pWeilaMsg) {
                pWeilaMsg->message = WL_GROUP_GET_GROUP_INFO_MSG;
            }
        } break;

        case WL_Group_GroupCommandId_GROUP_COMMAND_GET_BLACKLIST: {
            pWeilaMsg = weilapb_decodeGetGroupBlackListRsp(pData, dataSize);
            if (pWeilaMsg) {
                pWeilaMsg->message = WL_GROUP_GET_BLACKLIST_MSG;
            }
        } break;

        case WL_Group_GroupCommandId_GROUP_COMMAND_CHANGE_BLACKLIST: {
            pWeilaMsg = weilapb_decodeEmptyRsp(pData, dataSize);
            if (pWeilaMsg) {
                pWeilaMsg->message = WL_GROUP_CHANGE_BLACKLIST_MSG;
            }
        } break;

        case WL_Group_GroupCommandId_GROUP_COMMAND_CHANGE_MEMBERINFO: {
            if (commandType == WL_Service_CommandType_COMMAND_RESPONSE) {
                pWeilaMsg = weilapb_decodeEmptyRsp(pData, dataSize);
            } else {
                pWeilaMsg = weilapb_decodeChangeMemberInfoNtf(pData, dataSize);
            }
            if (pWeilaMsg) {
                pWeilaMsg->message = WL_GROUP_CHANGE_MEMBER_INFO_MSG;
            }
        } break;

        case WL_Group_GroupCommandId_GROUP_COMMAND_ANSWER_GROUP_INVITE: {
            if (commandType == WL_Service_CommandType_COMMAND_RESPONSE) {
                pWeilaMsg = weilapb_decodeEmptyRsp(pData, dataSize);
            } else {
                pWeilaMsg = weilapb_decodeAnswerGroupInviteNtf(pData, dataSize);
            }
            if (pWeilaMsg) {
                pWeilaMsg->message = WL_GROUP_ANSWER_GROUP_INVITE_MSG;
            }
        } break;

        case WL_Group_GroupCommandId_GROUP_COMMAND_GROUP_JOIN: {
            if (commandType == WL_Service_CommandType_COMMAND_RESPONSE) {
                pWeilaMsg = weilapb_decodeEmptyRsp(pData, dataSize);
            } else {
                pWeilaMsg = weilapb_decodeGroupJoinNtf(pData, dataSize);
            }
            if (pWeilaMsg) {
                pWeilaMsg->message = WL_GROUP_GROUP_JOIN_MSG;
            }
        } break;

        case WL_Group_GroupCommandId_GROUP_COMMAND_ANSWER_GROUP_JOIN: {
            if (commandType == WL_Service_CommandType_COMMAND_RESPONSE) {
                pWeilaMsg = weilapb_decodeEmptyRsp(pData, dataSize);
            } else {
                pWeilaMsg = weilapb_decodeAnswerGroupJoinNtf(pData, dataSize);
            }
            if (pWeilaMsg) {
                pWeilaMsg->message = WL_GROUP_ANSWER_GROUP_JOIN_MSG;
            }
        } break;

        case WL_Group_GroupCommandId_GROUP_COMMAND_BROADCAST: {
            if (commandType == WL_Service_CommandType_COMMAND_RESPONSE) {
                pWeilaMsg = weilapb_decodeEmptyRsp(pData, dataSize);
            } else {
                pWeilaMsg = weilapb_decodeBroadcastNtf(pData, dataSize);
            }
            if (pWeilaMsg) {
                pWeilaMsg->message = WL_GROUP_BROADCAST_MSG;
            }
        } break;

        case WL_Group_GroupCommandId_GROUP_EMBEDDED_COMMAND_GET_GROUPVERSION: {
            pWeilaMsg = weilapb_decodeEmbeddedGetGroupVersionRsp(pData, dataSize);
            if (pWeilaMsg) {
                pWeilaMsg->message = WL_GROUP_GET_EMBEDDED_GROUP_VER_MSG;
            }
        } break;

        case WL_Group_GroupCommandId_GROUP_EMBEDDED_COMMAND_GET_GROUPINFO: {
            if (commandType == WL_Service_CommandType_COMMAND_RESPONSE) {
                pWeilaMsg = weilapb_decodeGetEmbeddedGroupInfoRsp(pData, dataSize);
            }

            if (pWeilaMsg) {
                pWeilaMsg->message = WL_GROUP_GET_EMBEDDED_INFOS;
            }
        } break;

        case WL_Group_GroupCommandId_GROUP_COMMAND_NEW_MEMBER: {
            if (commandType == WL_Service_CommandType_COMMAND_NOTIFY) {
                pWeilaMsg = weilapb_decodeNewMemberNtf(pData, dataSize);
                if (pWeilaMsg) {
                    pWeilaMsg->message = WL_GROUP_NEW_MEMBER_NTF_MSG;
                }
            }
        }
    }

    return pWeilaMsg;
}
